import mongoose from 'mongoose'
import * as R from 'ramda'

const Message = mongoose.model('Message')
const User = mongoose.model('User')
const Dialog = mongoose.model('Dialog')
const ObjectId = mongoose.Types.ObjectId

const messageSelect = {
  belongsTo: 1,
  content: 1,
  meta: 1,
  _id: 1
}

const userSelect = {
  nickname: 1,
  avatar: 1,
  _id: 1
}

// 根据dialogId发送消息
export async function sendMessageByDialogId(belongsTo, dialogId, content) {
  const dialog = await Dialog.findOne({
    _id: ObjectId(dialogId),
    members: {
      $all: [ObjectId(belongsTo)]
    }
  })
  if (!dialog) return null
  dialog.showTo = dialog.members
  await dialog.save()
  let message = new Message({
    content,
    belongsTo,
    dialog: Object(dialogId),
  })
  await message.save()
  return await Message.findOne({
    _id: message._id
  }).populate({
    path: 'belongsTo',
    select: {...userSelect}
  }).select({
    ...messageSelect,
    dialog: 1
  })
}

// 发送一对一消息
export async function sendMessage(belongsTo, sendTo, content) {
  let dialog = await Dialog.findOneAndUpdate({
    type: 0,
    members: {
      $all: [ObjectId(belongsTo), ObjectId(sendTo)],
      $size: 2
    }
  }, {
    $addToSet: {
      showTo: { $each: [ObjectId(belongsTo), ObjectId(sendTo)] }
    }
  }, { new: true })
  if (!dialog) {
    dialog = new Dialog({
      type: 0,
      createdBy: belongsTo,
      members: [belongsTo, sendTo],
      showTo: [belongsTo, sendTo]
    })
    await dialog.save()
  }
  const message = new Message({
    content,
    belongsTo,
    dialog: dialog._id,
  })
  await message.save()

  return R.compose(
    R.forEachObjIndexed((item, key, obj) => { item && (obj[key] = message[key]) })
  )(Object.assign({dialog: 1}, messageSelect))
}

// 根据socketId查询单个用户信息
export async function getUserBySocketId(socketId) {
  return await User.findOne({
    socketId
  })
}

// 根据会话id标记已读
export async function signSingleDialog(dialogId, userId) {
  await Message.updateMany({
    belongsTo: {
      $ne: ObjectId(userId)
    },
    dialog: ObjectId(dialogId)
  }, {
    $addToSet: {
      read: ObjectId(userId)
    }
  }, {
    multi: true
  })
}

// 根据用户id获取一对一聊天室id
export async function getDialogByUserId(belongsTo, sendTo) {
  return await Dialog.findOne({
    type: 0,
    members: {
      $all: [ObjectId(belongsTo), ObjectId(sendTo)],
      $size: 2
    }
  })
}

// 一对一消息内容获取
// belongsTo为当前登录人id
export async function getMessageWithSomeOne(belongsTo, sendTo, skip = 0, size = 10) {
  skip = Number(skip)
  size = Number(size)
  const dialog = await Dialog.findOne({
    type: 0,
    members: {
      $all: [ObjectId(belongsTo), ObjectId(sendTo)],
      $size: 2
    }
  })
  if (dialog) {
    const query = {
      dialog: dialog._id
    }
    const total = await Message.find(query).countDocuments()
    return {
      data: await Message.find(query).sort({'meta.createdAt': -1}).skip(skip).limit(size).select({
        ...messageSelect
      }),
      result: 1,
      skip,
      size,
      total
    }
  } else {
    return {
      data: [],
      result: 1,
      skip,
      size,
      total: 0
    }
  }
}

// 根据dialogId获取群组消息列表
export async function getMultiMessagesByDialogId(userId, dialogId, skip = 0, size = 10) {
  skip = Number(skip)
  size = Number(size)
  const dialog = await Dialog.findOne({
    _id: ObjectId(dialogId),
    members: {
      $all: [ObjectId(userId)]
    }
  })
  if (!dialog) {
    return {
      result: 0,
      mes: '你还没有加入该群组'
    }
  }
  const query = {
    dialog: ObjectId(dialogId)
  }
  const total = await Message.find(query).countDocuments()
  return {
    data: await Message.find(query).sort({'meta.createdAt': -1}).skip(skip).limit(size).populate({
      path: 'belongsTo',
      select: {
        _id: 1,
        nickname: 1,
        avatar: 1
      }
    }).select({
      ...messageSelect
    }),
    result: 1,
    skip,
    size,
    total
  }
}

// 根据消息id获取消息详情
export async function getMessageById(id) {
  return await Message.findOne({
    _id: ObjectId(id)
  }).select({
    ...messageSelect
  })
}

// 根据用户id，消息id对单个消息进行标记已读
export async function signSingleMessage(userId, messageId) {
  if (!userId || !messageId) return
  const message = await Message.aggregate([{
    $match: {
      _id: ObjectId(messageId)
    }
  }, {
    $lookup: {
      from: 'dialogs',
      as: 'dialog',
      let: { dialogId: '$dialog' },
      pipeline: [{
        $match: {
          $and: [{
            $expr: {
              $eq: ['$_id', '$$dialogId']
            }
          }, {
            members: { $all: [ObjectId(userId)] }
          }]
        }
      }]
    }
  }, {
    $match: {
      dialog: {
        $gt: [{$size: '$dialog'}, 0]
      }
    }
  }, {$count: 'total'}])
  const total = message.length ? message[0].total : 0
  if (total === 0) return
  await Message.updateOne({
    _id: ObjectId(messageId),
    belongsTo: {
      $ne: ObjectId(userId)
    }
  }, {
    $addToSet: {
      read: ObjectId(userId)
    }
  })
}
